package k2platform.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wangyn on 17-3-9.
 */
public class ProtocolFieldUtil {
    private static Logger logger = LoggerFactory.getLogger(ProtocolFieldUtil.class);

    private static final String WT_PROTOCOL_MAP_FILE = "/wtProtocolMap.csv";
    private static final String PROTOCOL_FILE_PREFIX = "protocol-";
    private static final String COL_SEPRATOR = ",";
    private static final String KMXDATA_FIELDS_DESC_FILENAME = "/7sData_122.csv";
    private static final String PROTOCOL_FIELDGROUP_NAME = "/protocol-fieldGroup.csv";
    private static final String CONTROL_PROTOCOL_FIELD_NAME = "/protocol-field.csv";

    private static final String SQLIT_JDBC_DRIVER = "org.sqlite.JDBC";
    private static final String SQLIT_BASE_URL = "jdbc:sqlite:";

    /**
     * read KMX data fieldIds: the first col
     * 必须保留case
     * buildRecord key 必须是完全匹配，区分大小写
     *
     * @param gw7sFieldIdFile desc file: fieldId,fieldName,valueType
     * @return
     */
    public static List<String> gw7sFiledIds(String gw7sFieldIdFile) {
        logger.info("gw7sFiledIds:" + gw7sFieldIdFile);

        BufferedReader br = null;
        try {
            if (gw7sFieldIdFile == null || gw7sFieldIdFile.trim().isEmpty()) {
                br = new BufferedReader(new InputStreamReader(ProtocolFieldUtil.class.getResourceAsStream(KMXDATA_FIELDS_DESC_FILENAME)));
            } else {
                br = new BufferedReader(new FileReader(gw7sFieldIdFile));
            }

            return readCsvFileFields(br, 0);

        } catch (IOException e) {
            logger.error("gw7sFiledIds failed:" + e.getMessage());
            System.exit(1);
        } finally {
            closeBr(br);
        }

        return null;
    }

    /**
     * getProtWt7s
     *
     * @param prot7sDBfile sqlit db file path. example: /opt/k2data/configData.file
     * @return <wtid,protocolId>
     */
    public static Map<String, String> getProtWt7s(String prot7sDBfile) {
        if (prot7sDBfile == null || prot7sDBfile.trim().isEmpty()) {
            logger.error("protocol file path is null.");
            System.exit(-1);
        }
        logger.info("protocol wind turbine DB file:" + prot7sDBfile);
        String url = SQLIT_BASE_URL + prot7sDBfile;
        String wtSql = "select wtid,protocolid from wtinfo";

        try {
            Class.forName(SQLIT_JDBC_DRIVER);
        } catch (ClassNotFoundException e) {
            logger.error("sqlit load driver error." + e.getMessage());
            System.exit(-1);
        }
        Connection c = null;
        try {
            c = DriverManager.getConnection(url);
            Statement statement = c.createStatement();
            statement.execute("PRAGMA synchronous=OFF");
            statement.close();
        } catch (SQLException e) {
            logger.error("create sqlit connection error." + e.getMessage());
            System.exit(-1);
        }
        //select wtid,protocolid
        Statement statm = null;
        ResultSet rs = null;
        Map<String, String> proWtMap = new HashMap<>();
        try {
            statm = c.createStatement();
            rs = statm.executeQuery(wtSql);
            while (rs.next()) {
                String wtid = rs.getString(1).replace(" ", "");
                String protocolId = rs.getString(2).replace(" ", "");
                proWtMap.put(wtid, protocolId);
            }
        } catch (SQLException e) {
            logger.error(wtSql + " error." + e.getMessage());
            System.exit(-1);
        }
        //close db connection
        try {
            if (rs != null) {
                rs.close();
            }
            if (statm != null) {
                statm.close();
            }
            if (c != null) {
                c.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.info("prot id count: wt--" + proWtMap.keySet().size());
        return proWtMap;
    }

    public static Map<String, String> getProtWf7s(String prot7sDBfile) {
        if (prot7sDBfile == null || prot7sDBfile.trim().isEmpty()) {
            logger.error("protocol file path is null.");
            System.exit(-1);
        }
        logger.info("protocol wind farm DB file:" + prot7sDBfile);
        String url = SQLIT_BASE_URL + prot7sDBfile;
        String wtSql = "select wtid,wfid from wtinfo";

        try {
            Class.forName(SQLIT_JDBC_DRIVER);
        } catch (ClassNotFoundException e) {
            logger.error("sqlit load driver error." + e.getMessage());
            System.exit(-1);
        }
        Connection c = null;
        try {
            c = DriverManager.getConnection(url);
            Statement statement = c.createStatement();
            statement.execute("PRAGMA synchronous=OFF");
            statement.close();
        } catch (SQLException e) {
            logger.error("create sqlit connection error." + e.getMessage());
            System.exit(-1);
        }
        //select wtid,wfid
        Statement statm = null;
        ResultSet rs = null;
        Map<String, String> proWfMap = new HashMap<>();
        try {
            statm = c.createStatement();
            rs = statm.executeQuery(wtSql);
            while (rs.next()) {
                String wtid = rs.getString(1).replace(" ", "");
                String wfid = rs.getString(2).replace(" ", "");
                proWfMap.put(wtid, wfid);
            }
        } catch (SQLException e) {
            logger.error(wtSql + " error." + e.getMessage());
            System.exit(-1);
        }
        //close db connection
        try {
            if (rs != null) {
                rs.close();
            }
            if (statm != null) {
                statm.close();
            }
            if (c != null) {
                c.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.info("wind farm id count: wf--" + proWfMap.keySet().size());
        return proWfMap;
    }

    /**
     * getProtField7s
     *
     * @param prot7sDBfile sqlit db file path. example: /opt/k2data/configData.file
     * @return <protocolId, <fieldIds[toLowerCase]>>
     */
    public static Map<String, List<String>> getProtField7s(String prot7sDBfile) {
        if (prot7sDBfile == null || prot7sDBfile.trim().isEmpty()) {
            logger.error("protocol file path is null.");
            System.exit(-1);
        }
        logger.info("protocol field id DB file path: " + prot7sDBfile);
        String url = SQLIT_BASE_URL + prot7sDBfile;
        String fieldSql = "SELECT protocolid,iecpath from propaths where iecpath <> 'WTUR.Tm.Rw.Dt' and transtype='1' and bsave=1  ORDER BY protocolid, pathid ";
        try {
            Class.forName(SQLIT_JDBC_DRIVER);
        } catch (ClassNotFoundException e) {
            logger.error("sqlit load driver error." + e.getMessage());
            System.exit(-1);
        }
        Connection c = null;
        try {
            c = DriverManager.getConnection(url);
            Statement statement = c.createStatement();
            statement.execute("PRAGMA synchronous=OFF");
            statement.close();
        } catch (SQLException e) {
            logger.error("create sqlit connection error." + e.getMessage());
            System.exit(-1);
        }
        //select protocolid , fieldid
        Statement statm = null;
        ResultSet rs = null;
        Map<String, List<String>> proFieldMap = new HashMap<>();
        try {
            statm = c.createStatement();
            rs = statm.executeQuery(fieldSql);
            while (rs.next()) {
                String protocolId = rs.getString(1).replace(" ", "");
                String fieldId = rs.getString(2).replace(" ", "").replace(".", "_").toLowerCase();
                if (proFieldMap.containsKey(protocolId)) {
                    proFieldMap.get(protocolId).add(fieldId);
                } else {
                    List<String> fields = new ArrayList<>();
                    fields.add(fieldId);
                    proFieldMap.put(protocolId, fields);
                }
            }
        } catch (SQLException e) {
            logger.error(fieldSql + " error." + e.getMessage());
            System.exit(-1);
        }
        //close db connection
        try {
            if (rs != null) {
                rs.close();
            }
            if (statm != null) {
                statm.close();
            }
            if (c != null) {
                c.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.info("prot id count:field-- " + proFieldMap.keySet().size());

        return proFieldMap;
    }

    /**
     * read csv file
     *
     * @param br       bufferedreader
     * @param colIndex index
     * @return
     * @throws IOException
     */
    public static List<String> readCsvFileFields(BufferedReader br, int colIndex) throws IOException {
        String line = null;
        List<String> field = new ArrayList<String>();
        //skip firstLine
        line = br.readLine();
        if (line != null && !"".equalsIgnoreCase(line)) {
            while ((line = br.readLine()) != null) {
                String[] cols = line.split(COL_SEPRATOR);
                if (cols.length >= 1) {
                    //trim and to ; *****必须保留原来的case×××××
                    //将fieldId中的.替换成_
                    field.add(cols[0].trim().replace(".", "_"));
                }
            }
            return field;
        }

        return null;
    }

    /**
     * field control: process protocolFiles of fieldGroup
     *
     * @return protocol fieldGroup map key: code , value: fieldGroupId
     */
    public static Map<Integer, String> readProtocolFieldGroupId() {
        Map<Integer, String> protocolFieldGroups = new HashMap<>();
        InputStream ins = null;
        BufferedReader br = null;
        String line = null;
        try {
            ins = ProtocolFieldUtil.class.getResourceAsStream(PROTOCOL_FIELDGROUP_NAME);
            br = new BufferedReader(new InputStreamReader(ins));
            if (br.readLine() != null) {
                while ((line = br.readLine()) != null) {
                    String[] index = line.split(",");
                    if (index.length >= 2) {
                        protocolFieldGroups.put(Integer.valueOf(index[0].trim()), index[1].trim());
                    } else {
                        logger.error("protocol file of field group is error.");
                        System.exit(-1);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("process protocolFile of fieldGroup error." + e.getMessage());
            System.exit(-1);
        } finally {
            closeBr(br);
        }
        return protocolFieldGroups;

    }

    /**
     * field control: process protocolFiles of field
     *
     * @return protocol field map key: code, value: fieldId
     */
    public static Map<Integer, String> readProtocolControlFieldId() {
        Map<Integer, String> protocolFields = new HashMap<>();
        InputStream ins = null;
        BufferedReader br = null;
        String line = null;
        try {
            ins = ProtocolFieldUtil.class.getResourceAsStream(CONTROL_PROTOCOL_FIELD_NAME);
            br = new BufferedReader(new InputStreamReader(ins));
            if (br.readLine() != null) {
                while ((line = br.readLine()) != null) {
                    String[] index = line.split(",");
                    if (index.length >= 2) {
                        protocolFields.put(Integer.valueOf(index[0].trim()), index[1].trim());
                    } else {
                        logger.error("protocol file of field is error.");
                        System.exit(-1);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("process protocolFile of field error." + e.getMessage());
            System.exit(-1);
        } finally {
            closeBr(br);
        }
        return protocolFields;
    }

    /**
     * close bufferedreader
     *
     * @param br bufferedreader
     */
    private static void closeBr(BufferedReader br) {
        try {
            if (br != null) {
                br.close();
            }
            br = null;
        } catch (IOException e) {
            logger.error("inputStream close failed." + e.getMessage());
        }
    }

    public static void copyFile(File src, File dest) throws IOException {
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dest);
        byte[] buffer = new byte[4096];
        int length;
        while ((length = in.read(buffer)) > 0) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
    }

    public static void main(String[] args) {
        // gw7sFiledIds(null);
        //getProtWt7s(null);
        // getProtField7s(null);
        // System.out.println(System.getProperty("user.dir"));
        // String classPath = ProtocolFieldUtil.class.getClass().getResource("/").getPath();
        // String subStr = "/target/";
        // System.out.println(classPath.substring(0, classPath.indexOf(subStr)));
        // System.out.println(ProtocolFieldUtil.class.getClass().getResource("/").getPath());
        // readProtocolFieldGroupId();
        //readProtocolControlFieldId();
    }
}
